<template>
  <view
    class="text"
    :class="[
      `text--${type}`,
      `text--fz-${getSize}`,
      `text--align-${align}`,
      { 'text--bold': bold, 'text--ellipsis-n': line },
    ]"
    :style="[getStyle]"
    @click="handleClick"
  >
    <slot v-if="$slots.leftText" />
    <template v-else>
      {{ leftText }}
    </template>
    <template v-if="filter"> {{ midText }} </template>
    <slot v-else-if="$slots.default" />
  </view>
</template>

<script lang="ts">
import { defineComponent, ref, computed, inject } from '@vue/composition-api'
import addUnit from '@/utils/add-unit'
import addColor from '@/utils/add-color'
import filters from '@/utils/filters'

export default defineComponent({
  props: {
    type: {
      type: String,
      default: '',
    },
    line: {
      type: [String, Number],
      default: null,
    },
    filter: {
      type: String,
      default: null,
    },
    filterText: {
      type: [String, Number],
      default: '',
    },
    statusMap: {
      type: Object,
      default: () => ({}),
    },
    color: {
      type: String,
      default: 'inherit',
    },
    text: {
      type: [String, Number],
      default: '',
    },
    leftText: {
      type: [String, Number],
      default: '',
    },
    marginLeft: {
      type: [String, Number],
      default: '',
    },
    marginRight: {
      type: [String, Number],
      default: '',
    },
    bold: {
      type: Boolean,
      default: false,
    },
    size: {
      type: [Number, String],
      default: null,
    },
    align: {
      type: String,
      default: 'inherit',
    },
  },
  emits: ['click'],
  options: {
    virtualHost: true, //  将自定义节点设置成虚拟的，更加接近Vue组件的表现。我们不希望自定义组件的这个节点本身可以设置样式、响应 flex 布局等，而是希望自定义组件内部的第一层节点能够响应 flex 布局或者样式由自定义组件本身完全决定
  },
  setup(props, { emit }) {
    const midText = ref()
    const textParent: any = inject('textGroup', null)

    if (props.filter) {
      // filter 只支持 props.text
      midText.value =
        props.filter.split('|').reduce((prev, str) => {
          const [filterFn, argsStr] = str.trim().split('(')
          const initArgs = argsStr ? argsStr.slice(0, -1).split(',') : []
          const filterArgs = [prev, ...initArgs.map((x) => JSON.parse(x.trim().replace(/'/g, '"')))]
          if (filterFn === 'status') {
            return filters['status'](prev, props.statusMap)
          }
          return filters[filterFn.trim()](...filterArgs)
        }, props.filterText || '') || ''
    }

    const getStyle = computed(() => {
      const sizeVal = getSize.value
      const obj: any = {}

      if (sizeVal !== null) {
        obj.fontSize = addUnit(Math.max(parseFloat(sizeVal + ''), 24))
      }

      if (props.marginLeft) {
        obj.marginLeft = addUnit(props.marginLeft)
      }

      if (props.marginRight) {
        obj.marginRight = addUnit(props.marginRight)
      }

      if (props.color) {
        obj.color = addColor(props.color)
      }

      if (!props.line) {
        return obj
      }

      return {
        ...obj,
        '-webkit-line-clamp': props.line,
      }
    })

    const handleClick = (e) => {
      emit('click', e)
    }

    const getSize = computed(() => {
      if (props.size !== null) {
        return props.size
      }

      if (textParent) {
        return textParent.size
      }

      return null
    })

    return {
      midText,
      getStyle,
      handleClick,
      getSize,
    }
  },
})
</script>
<style lang="scss" scoped>
.text {
  display: inline-block;
  // align-items: center;
  &--primary {
    color: $--font-primary-c;
  }
  &--danger {
    color: $--danger-c;
  }
  &--success {
    color: $--success-c;
  }
  &--warning {
    color: $--warning-c;
  }
  &--info {
    color: $--info-c;
  }
  &--regular {
    color: $--font-regular-c;
  }
  &--secondary {
    color: $--font-secondary-c;
  }
  &--bold {
    font-weight: bold;
  }
  // &--ellipsis {
  //   display: block;
  //   overflow: hidden;
  //   text-overflow: ellipsis;
  //   white-space: nowrap;
  // }
  &--ellipsis-n {
    word-break: break-all;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  &--fz-16 {
    @include fz16;
  }
  &--fz-18 {
    @include fz18;
  }
  &--fz-20 {
    @include fz20;
  }
  &--fz-22 {
    @include fz22;
  }
  &--align-left {
    text-align: left;
    transform-origin: left center;
  }
  &--align-center {
    text-align: center;
    transform-origin: center center;
  }
  &--align-right {
    text-align: right;
    transform-origin: right center;
  }
}
</style>
